upon
A simple, powerful template engine.
Features
Syntax
- Expressions:
{{ user.name }}
- Conditionals:
{% if user.enabled %} ... {% endif %}
- Loops:
{% for user in users %} ... {% endfor %}
- Nested templates:
{% include "nested" %}
- Configurable delimiters:
<? user.name ?>
,(( if user.enabled ))
- Arbitrary filter functions:
{{ user.name | replace: "\t", " " }}
Engine
- Clear and well documented API
- Customizable value formatters:
{{ user.name | escape_html }}
- Render to a
String
or anystd::io::Write
implementor - Render using any
serde
serializable values - Convenient macro for quick rendering:
upon::value!{ name: "John", age: 42 }
- Minimal dependencies and decent runtime performance
Getting started
Your entry point is the Engine
struct. The engine stores the syntax
config, filter functions, and compiled templates. Generally, you only need
to construct one engine during the lifetime of a program.
let engine = new;
Next, .add_template
is used to compile and store a
template in the engine.
engine.add_template?;
Finally, the template is rendered by fetching it using
.get_template
and calling
.render
.
let template = engine.get_template.unwrap;
let result = template.render?;
assert_eq!;
If the lifetime of the template source is shorter than the engine lifetime
or you don’t need to store the compiled template then you can also use the
.compile
function to return the template directly.
let template = engine.compile?;
let result = template.render?;
assert_eq!;
Examples
Render using structured data
Here is the same example as above except using derived data.
let ctx = Context ;
let result = new
.compile?
.render?;
assert_eq!;
Transform data using filters
Data can be transformed using registered filters.
let mut engine = new;
engine.add_filter;
let result = engine
.compile?
.render?;
assert_eq!;
See the Filter
trait documentation for more information on filters.
Render a template using custom syntax
The template syntax can be set by constructing an engine using
Engine::with_syntax
.
let syntax = builder.expr.block.build;
let result = with_syntax
.compile?
.render?;
assert_eq!;
Render a template to an impl io::Write
You can render a template directly to a buffer implementing io::Write
by using .render_to_writer()
.
use io;
let stdout = new;
new
.compile?
.render_to_writer?;
Add and use a custom formatter
You can add your own custom formatter’s or even override the default
formatter using Engine::set_default_formatter
. The following example
shows how you could add debug
formatter to the engine.
use Write;
use ;
let mut engine = new;
engine.add_formatter;
let result = engine
.compile?
.render?;
assert_eq!;
Benchmarks
The following shows a violin plot of the benchmark results for upon
compared
to the following template rendering engines.
Obviously, each of these engines has a completely different feature set so this just compares the performance of some of the features that they share.
Host
- MacBook Pro (14-inch, 2021)
- Chipset: Apple M1 Pro
- Memory: 16 GB
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.